/***************************************************************************
 *   Copyright (C) 2006 by Grzegorz Latarowski                             *
 *   g.latarowski@gmail.com                                                *
 *                                                                         *
 *   Project: AutoStop (kodowa nazwa do zmiany)                            *
 *                                                                         *
 ***************************************************************************/


#ifndef GTYPES_H
#define GTYPES_H

//----------------------------------------------------------------------------
// includy qtoskie

#include <QtGui>
#include <QtCore>


//----------------------------------------------------------------------------
// includy



//----------------------------------------------------------------------------
// definy
/// Na przemian 10101010.
#define MAGIC_NUMBER 0xAA




// ------------------------------- GItem{} -----------------------------------
/*!
 * Szablon klas wysyłanych w sieć.
 */
// ---------------------------------------------------------------------------
class GItem : public QObject
{

public:
        /*!
        * Konstruktor nic nie robiący.
        */
    GItem(QObject * parent = 0) : QObject(parent) {}

        /*!
        * Metoda zapisu danych do strumienia. Musi być reimplementowana.
        */
    virtual void write(QDataStream & /*out*/, quint32 /*version*/) {};
        /*!
        * Metoda odczytu danych ze strumienia. Musi być reimplementowana.
        */
    virtual void read(QDataStream & /*in*/, quint32 /*version*/) {};
    
}; // class GItem
// ---------------------------------------------------------------------------




// ---------------------------- GHeader{} ------------------------------------
/*!
* Klasa opisuje nagłówek typu danych wykorzystywanych w projekcie i kodowej
* nazwe AutoStop (która mam nadzieje zostanie zmieniona).
*
* Jeśli nagłówek w wersji pierwszej spotka dane typu wersji kolejnej
* to zaczyta tylko to co potrafii a reszte pozostawi w strumieniu.
 */
// ---------------------------------------------------------------------------
class GHeader : public QObject
{
Q_OBJECT;

public:
        /*!
        * Konstruktor.
        * Ustawia _magicNumber na MAGIC_NUMBER
        * i inicjalizuje pozostałe pola nagłówka.
        */
    GHeader(QObject * parent = 0);
    
        /*!
        * Zwraca magiczną liczbę.
        */
    quint8 magicNumber() const { return _magicNumber; }
        /*!
        * Zwraca łączny rozmiar pól prywatnych nagłówka.
        */
    qint64 headerSize() const { return _headerSize; }
        /*!
        * Zwraca rozmiar danych obiektu do którego należy.
        * -1 jeśli nie ustawione.
        */
    qint64 dataSize() const { return _dataSize; }
        /*!
        * Zwraca typ obiektu do którego należy.
        * -1 jeśli nie ustawione.
        */
    qint32 itemType() const { return _itemType; }
        /*!
        * Oblicza rozmiar pól prywatnych nagłówka i zwraca go.
        */
    qint64 size();
    
public slots:
        /*!
        * Ustawia magiczną liczbę.
        */
    void setMagicNumber(const quint8 magicNumber) { _magicNumber = magicNumber; }
        /*!
        * Ustawia wielkość nagłówka.
        */
    void setHeaderSize(const qint64 headerSize) { _headerSize = headerSize; }
        /*!
        * Ustawia rozmiar danych obiektu w którym znajduje się nagłówek.
        * Inicjalizowany jest -1.
        */
    void setDataSize(const quint32 dataSize) { _dataSize = dataSize; }
        /*!
        * Ustawia typ obiektu parenta. Domyślnie -1 czyli nie znany.
        */
    void setItemType(const qint32 itemType) { _itemType = itemType; }
    
    
private:
        /// Zmienna magiczna, jej poprawność daje szanse na poprawność danych.
        /// Posłuży jako pierwszy etap poprawności danych.
    quint8 _magicNumber;
        /// Rozmiar nagłówka w bajtach. Ustawiany automatycznie.
    qint64 _headerSize;
        /// Rozmiar danych w danym obiekcie. -1 jeśli nie ustwiony
    qint64 _dataSize;
        /// Zmienna określa typ obiektu który zawiera dany nagłówek.
    qint32 _itemType;


}; // class GBaseHeader

// powiązane operacje wejścia/wyjścia
QDataStream & operator << (QDataStream & out, const GHeader & header);
QDataStream & operator >> (QDataStream & in, GHeader & header);
// ---------------------------------------------------------------------------




// ---------------------------- GEvent{} -------------------------------------
/*!
* Klasa reprezentuje obrazek. Zawiera zdjęcie, opis, czas zdarzenia.
* Udostępnia metody strumieniowego zapisu i odczytu zdjęcia.
*/
// ---------------------------------------------------------------------------
class GEvent : public QObject
{
Q_OBJECT;

public:
        /*!
        * Konstruktor. Ustawia bieżącą datę i czas.
        */
    GEvent(QObject * parent = 0);
    
        /*!
        * Zwraca opis obrazka.
        */
    QString description()const { return _description; }
        /*!
        * Zwraca date i czas wykonania obrazka.
        */
    QDateTime dateTime()const { return _dateTime; }
        /*!
        * Zwraca referencje do obrazka.
        */
    QByteArray eventData()const { return _eventData; }
        /*!
        * Oblicza rozmiar pól prywatnych gpicture i zwraca go.
        * 
        * Uwaga! Funkcja kopiuje wszystkie pola do binarnego bufora
        * a następnie zwraca jego rozmiar. Jej zastosowanie może
        * niepotrzebnie użyć za dużo RAMu. Obiekt który jest właścicielem
        * obiektu tego typu powienien sam obliczać rozmiar na prywatnym
        * buforze.
        */
    qint64 size();
        /*!
        * Zapisuje zdjęcie picture do obiektu.
        */
    QByteArray & operator << (QByteArray &eventData);
        /*!
        * Do zdjęcia picture zapisuje zdjęcie z obiektu.
        */
    QByteArray & operator >> (QByteArray &eventData);

    
public slots:
        /*!
        * Ustawia opis.
        */
    void setDescription(const QString &description) { _description = description; }
        /*!
        * Ustawia date i czas.
        */
    void setDateTime(const QDateTime &dateTime) { _dateTime = dateTime; }
        /*!
        * Ustawia zdjęcie.
        */
    void setEventData(const QByteArray &eventData) { _eventData = eventData; }

private:
        /// Opis obrazka.
    QString _description;
        /// Data i czas zapisu obrazka.
    QDateTime _dateTime;
        /// Obrazek.
    QByteArray _eventData;

}; // class GEvent

// powiązane operacje wejścia/wyjścia
QDataStream & operator << (QDataStream & out, const GEvent & event);
QDataStream & operator >> (QDataStream & in, GEvent & event);
// ---------------------------------------------------------------------------



#endif // GTYPES_H





